#include <all_header.h>
static SemaphoreHandle_t sem;
static boot_app_task_notify_state_t state;

static void boot_app(void) {
	// jump addr
	uint32_t app_addr = *(uint32_t*) (JUMP_APP_FLASH_ADDR + 4); /// assemble must add 1
	__set_CONTROL(0);
	((void (*)(void)) app_addr)();
}

static void start_lptimer() {
	ASSERT(hlptim1.Init.Clock.Prescaler == LPTIM_PRESCALER_DIV1);
	ASSERT(HAL_LPTIM_TimeOut_Start_IT(&hlptim1,32) == HAL_OK); // 32768
}

static void stop_lptimer() {
	HAL_LPTIM_TimeOut_Stop_IT(&hlptim1);
	HAL_LPTIM_DeInit(&hlptim1);
}

static inline void enter_sleep(void) {
	HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}

void boot_app_task_init(void) {
	sem = xSemaphoreCreateBinary();
	ASSERT(sem);
}

void boot_app_task_run(void *arg) {
	while (true) {
		ASSERT(xSemaphoreTake(sem,portMAX_DELAY) == pdTRUE);
		switch (state) {
		case Boot_App_Task_Notify_State_Boot_App:
			vTaskSuspendAll();
			start_lptimer();
			enter_sleep();
			stop_lptimer();
			boot_app();
			break;
		case Boot_App_Task_Notify_State_Reset:
			RESET();
			break;
		}
	}
}

void boot_app_task_notify(boot_app_task_notify_state_t st) {
	state = st;
	xSemaphoreGive(sem);
}

void boot_app_task_direct_boot_app(void) {
	boot_app();
}
